package com.crl.nfp.config;

import com.cars.util.json.JsonResultUtil;
import com.cars.util.json.JsonUtil;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;

/**
 * 后端服务发生异常，进入Fallback类
 *
 * @author 宋长军
 * @date 2019/10/11 12:37
 */
public class ZuulFallbackProvider implements FallbackProvider, Serializable {

    private static final long serialVersionUID = 2156339066418780736L;

    private static final Logger LOGGER = LoggerFactory.getLogger("operationLog");

    private String message = JsonUtil.toStr(JsonResultUtil.error("服务异常，请稍后再试！"));

    @Override
    public String getRoute() {
        return "*";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {

        LOGGER.warn("route: {}, exceptionType: {}, stackTrace: {}", route, cause.getClass().getName(), cause.getStackTrace());

        if (cause instanceof HystrixTimeoutException) {
            message = "HystrixTimeoutException";
            return response(HttpStatus.GATEWAY_TIMEOUT, message);
        } else {
            return this.fallbackResponse();
        }
    }

    private ClientHttpResponse fallbackResponse() {
        return this.response(HttpStatus.INTERNAL_SERVER_ERROR, message);
    }

    private ClientHttpResponse response(final HttpStatus status, String message) {

        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return status;
            }

            @Override
            public int getRawStatusCode() {
                return status.value();
            }

            @Override
            public String getStatusText() throws IOException {
                return status.getReasonPhrase();
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream(message.getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                MediaType mediaType = new MediaType("application", "json", StandardCharsets.UTF_8);
                headers.setContentType(mediaType);
                return headers;
            }
        };
    }
}
